package com.xdf.whiteaccount.config.datasource;

import com.xdf.whiteaccount.config.properties.DbConfig;
import com.xdf.whiteaccount.enums.DatasourceKey;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: white-account
 * @description: 动态数据源
 * @author: 张柯
 * @create: 2021-06-11 09:49
 **/
public class DynamicDataSource extends AbstractRoutingDataSource {
    private static DynamicDataSource instance;
    private static ConcurrentHashMap<Object, Object> dynamicTargetDataSources;
    private static final ThreadLocal<String> CURRENT_DATASOURCE = ThreadLocal.withInitial(() -> DatasourceKey.PRIMARY_KEY);
    private static final ThreadLocal<String> STORAGE_DATASOURCE = ThreadLocal.withInitial(() -> DatasourceKey.PRIMARY_KEY);

    public static DynamicDataSource getInstance() {
        if (instance == null) {
            synchronized (DynamicDataSource.class) {
                if (instance == null) {
                    instance = new DynamicDataSource();
                }
            }
        }
        return instance;
    }

    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        dynamicTargetDataSources = new ConcurrentHashMap<>(targetDataSources);
        super.setTargetDataSources(dynamicTargetDataSources);
    }

    /**
     * 清除DS
     */
    public synchronized void clearDataSource() {
        CURRENT_DATASOURCE.remove();
    }

    /**
     * 设置当前线程用户所属数据库
     *
     * @param key
     */
    public synchronized void setStorageDatasource(String key) {
        STORAGE_DATASOURCE.set(key);
    }

    /***
     * 获取当前保存的数据源
     * @return
     */
    public synchronized String getStorageDatasource() {
        return STORAGE_DATASOURCE.get();
    }

    /**
     * 切换数据源
     *
     * @param key
     * @return
     */
    public synchronized boolean switchDataSource(String key) {
        if (dynamicTargetDataSources.containsKey(key)) {
            CURRENT_DATASOURCE.set(key);
            return true;
        }
        return false;
    }

    /**
     * 获取当前数据源字符
     *
     * @return
     */
    public synchronized String getCurrentDataSourceName() {
        return String.valueOf(this.determineCurrentLookupKey());
    }

    /**
     * 设置默认数据源
     *
     * @return
     */
    public synchronized boolean switchDefault() {
        CURRENT_DATASOURCE.set(DatasourceKey.PRIMARY_KEY);
        return true;
    }

    /**
     * 创建与切换数据源
     *
     * @param config 数据库配置类
     * @return
     */
    public synchronized boolean addAndSwitchDataSource(DbConfig config) {
        if (dynamicTargetDataSources.containsKey(config.getName())) {
            CURRENT_DATASOURCE.set(config.getName());
            return true;
        }
        HikariDataSource dataSource = null;
        try {
            dataSource = DbConfig.getDataSource(config);
            dynamicTargetDataSources.put(config.getName(), dataSource);
            afterPropertiesSet();
            CURRENT_DATASOURCE.set(config.getName());
        } catch (Exception e) {
            if (dataSource != null) {
                dataSource.close();
            }
            logger.error("添加数据源失败,失败信息:" + e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 获取当前所有的Key
     *
     * @return
     */
    public List<String> getDataSourceKeys() {
        List<String> keys = new ArrayList<>();
        for (Map.Entry<Object, Object> s : dynamicTargetDataSources.entrySet()) {
            keys.add(String.valueOf(s.getKey()));
        }
        return keys;
    }

    @Override
    protected Object determineCurrentLookupKey() {
        logger.debug("当前调用的数据库名称标识:" + CURRENT_DATASOURCE.get());
        return CURRENT_DATASOURCE.get();
    }
}
